import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;


public class Server {
	
	private static final Map<String, Socket> socketByHostName = Maps.newHashMap();

	private static final class RunnableImplementation implements Runnable {
		private static final String SEPARATOR = ":::";
		private final Socket socket;
		

		private RunnableImplementation(Socket socket) {
			this.socket = socket;
			socketByHostName.put(socket.getLocalAddress().getHostName(), socket);
		}

		@Override
		public void run() {
			try {
				BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				String message = br.readLine();
				BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
				bw.write(message + " Server receive!!!");
				String hostName = message.substring(0, message.indexOf(SEPARATOR));
				Socket receiverSocket = socketByHostName.get(hostName);
				Preconditions.checkNotNull(receiverSocket, "Socket by hostName " + hostName + " is not found");
				bw = new BufferedWriter(new OutputStreamWriter(receiverSocket.getOutputStream()));
				bw.write(message);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static ServerSocket ss;

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		try {
			ExecutorService threadPool = Executors.newCachedThreadPool();
			
			InetAddress localHost = InetAddress.getLocalHost();
			
			String hostAddress = localHost.getHostAddress();
			String hostName = localHost.getHostName();
			int port = 5555;
			System.out.println(hostAddress + " by " + hostName + ", port " + port);
			
			ss = new ServerSocket(port);
			System.out.println("Server is start");
			while (true) {
			final Socket socket = ss.accept();
			threadPool.execute(new RunnableImplementation(socket));
			Thread.sleep(100);
			
			}
			
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			ss.close();
		}
	}

}
